module phase_shifter #(
    parameter DATA_WIDTH = 14,
    parameter RAM_ADDR_FULL = 1024,
    parameter RAM_ADDR_WIDTH = 10
)
(
    input  wire sys_clk,
    input  wire sys_rst,
 
    input  wire [DATA_WIDTH     - 1: 0] in_data,
    input  wire                         in_strobe,
 
    input  wire [RAM_ADDR_WIDTH - 1: 0] in_phase,
    input  wire [RAM_ADDR_WIDTH - 1: 0] full_address,
    input  wire                         phase_valid,

    output reg  [DATA_WIDTH     - 1: 0] out_data,
    output reg                          out_valid
);

reg [RAM_ADDR_WIDTH - 1 : 0] ram_in_addr;
reg [RAM_ADDR_WIDTH - 1 : 0] ram_out_addr;
reg [RAM_ADDR_WIDTH - 1 : 0] address;
reg [RAM_ADDR_WIDTH - 1 : 0] phase;
reg [DATA_WIDTH - 1: 0] data_ram [0 : RAM_ADDR_FULL - 1];

reg in_strobe_dly;
reg inited;

always @ (posedge sys_clk)
    if(sys_rst)
        in_strobe_dly <= 0;
    else
        in_strobe_dly <= in_strobe;

always @ (posedge sys_clk)
    if(sys_rst) begin
        ram_in_addr <= 0;
        inited <= 0;
    end
    else if(in_strobe) begin
        ram_in_addr <= ram_in_addr == address - 1 ? 0 : ram_in_addr + 1;
        if(ram_in_addr == address - 1 )
            inited <= 1;
    end
    
always @ (posedge sys_clk)
    if(sys_rst)
        ram_out_addr <= 0;
    else if(in_strobe_dly)
        ram_out_addr <= ram_in_addr + phase <= address - 1 ? ram_in_addr + phase : ram_in_addr + phase - address;

always @ (posedge sys_clk)
    if(sys_rst) begin
        address <= 0;
        phase <= 0;
    end
    else if(phase_valid) begin
        address <= full_address;
        phase <= in_phase;
    end

always @ (posedge sys_clk)
    if(in_strobe)
        data_ram[ram_in_addr] <= in_data;

always @ (posedge sys_clk)
    if(sys_rst)
        out_data <= 0;
    else if(inited && in_strobe_dly)
        out_data <= data_ram[ram_out_addr];

always @ (posedge sys_clk)
    if(sys_rst)
        out_valid <= 1'b0;
    else if(inited && in_strobe_dly)
        out_valid <= 1'b1;
    else
        out_valid <= 1'b0;

endmodule
